package com.song.webutil;


import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;


/**
 * @author wangsong
 * @version 1.0
 *          http工具包
 */
public class HttpUtils {
    //cookie仓库
    private CookieStore gCurCookieStore = null;
    private int defaulttimeout = 5000;


    public HttpUtils() {
        //初始化cookie仓库
        gCurCookieStore = new BasicCookieStore();
    }

    /**
     * 得到系统当前的时间
     *
     * @return long
     */
    public long calcTimeStart() {
        long startMilliSec = 0;
        startMilliSec = System.currentTimeMillis();
        return startMilliSec;
    }

    /**
     * 把时间格式化成字符串
     *
     * @param date   时间Date
     * @param format 格式化字符串
     * @return 时间字符串
     * //Thu Nov 21 18:11:56 CST 2013  -->> 2013-11-21_181156
     */
    public String dateToString(Date date, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        String datetimeStr = simpleDateFormat.format(date);
        return datetimeStr;
    }


    /**
     * 把一个文件中的内容读出来
     *
     * @param fullFilename 文件路径
     * @return 文件中的内容String
     */
    public String readFileContentStr(String fullFilename) {
        String readOutStr = null;
        BufferedReader bufReader = null;

        try {
            InputStreamReader isr = new InputStreamReader(new FileInputStream(fullFilename), "UTF-8");

            bufReader = new BufferedReader(isr);

            String lineSeparator = System.getProperty("line.separator");

            String line = "";
            while ((line = bufReader.readLine()) != null) {
                readOutStr += line + lineSeparator;
            }
            bufReader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return readOutStr;
    }


    /**
     * 把字符串中的内容写入中文件中
     *
     * @param strToOutput  写入的字符串
     * @param fullFilename 文件路径
     * @return 成功则返回true
     */
    public boolean outputStringToFile(String strToOutput, String fullFilename) {
        boolean ouputOk = true;
        try {
            File newTextFile = new File(fullFilename);
            FileWriter fw;
            fw = new FileWriter(newTextFile);
            fw.write(strToOutput);
            fw.close();
        } catch (IOException e) {
            ouputOk = false;
        }
        return ouputOk;
    }

    /**
     * 在控制台打印出某个网址全部的cookie
     *
     * @param cookieList 全部的cookieList
     * @param url        cookie网址
     */
    public void dbgPrintCookies(List<Cookie> cookieList, String url) {
        if ((null != url) && (!url.isEmpty())) {
            System.out.println("Cookies for " + url);
        }
        for (Cookie ck : cookieList) {
            System.out.println(ck);
        }
    }

    /**
     * 在控制台打印出全部的cookie
     *
     * @param cookieStore cookie仓库
     */
    public void dbgPrintCookies(CookieStore cookieStore) {
        dbgPrintCookies(cookieStore, null);
    }

    /**
     * 在控制台打印出某个网址全部的cookie
     *
     * @param cookieStore cookie仓库
     * @param url         cookie网址
     */
    public void dbgPrintCookies(CookieStore cookieStore, String url) {
        List<Cookie> cookieList = cookieStore.getCookies();
        dbgPrintCookies(cookieList, url);
    }

    /**
     * 在控制台打印出某个网址全部的cookie
     *
     * @param cookieList 全部的cookieList
     */
    public void dbgPrintCookies(List<Cookie> cookieList) {
        dbgPrintCookies(cookieList, null);
    }

    /**
     * 得到 cookie仓库
     *
     * @return
     */
    public CookieStore getCurCookieStore() {
        return gCurCookieStore;
    }

    /**
     * 在控制台打印出某个网址全部的cookie
     */
    public List<Cookie> getCurCookieList() {
        if (null != gCurCookieStore) {
            return gCurCookieStore.getCookies();
        } else {
            return null;
        }
    }

    /**
     * 设置新的cookie仓库
     *
     * @param newCookieStore
     */
    public void setCurCookieStore(CookieStore newCookieStore) {
        gCurCookieStore = newCookieStore;
    }

    /**
     * 设置新的cookie仓库
     *
     * @param newCookieList
     */
    public void setCurCookieList(List<Cookie> newCookieList) {
        gCurCookieStore.clear();
        for (Cookie eachNewCk : newCookieList) {
            gCurCookieStore.addCookie(eachNewCk);
        }
    }


    /**
     * get方式或者post方式请求URL并解析
     *
     * @param url        请求的URL
     * @param headerDict 请求求文件 可以为空，则用默认的头文件
     * @param postDict   post请求参数 如果为空，也自动调用get方式
     * @param timeout    请求超时时间 默认问5000毫秒
     * @return 请求的返回的response
     */
    public HttpResponse getUrlResponse(
            String url,
            List<NameValuePair> headerDict,
            List<NameValuePair> postDict,
            int timeout
    ) {
        if (timeout != 0) {
            defaulttimeout = timeout;
        }
        HttpResponse response = null;
        HttpUriRequest request = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        RequestConfig requestConfig =
                RequestConfig.custom().setSocketTimeout(defaulttimeout).
                        setConnectTimeout(defaulttimeout).build();//设置请求和传输超时时间

        if (postDict != null) {
            HttpPost postReq = new HttpPost(url);
            postReq.setConfig(requestConfig);
            if (headerDict != null) {
                for (NameValuePair entry : headerDict) {
                    postReq.setHeader(entry.getName(), entry.getValue());
                }
            }
            try {
                HttpEntity postBodyEnt = new UrlEncodedFormEntity(postDict);
                postReq.setEntity(postBodyEnt);
            } catch (Exception e) {
                e.printStackTrace();
            }
            request = postReq;
        } else {
            HttpGet getReq = new HttpGet(url);
            getReq.setConfig(requestConfig);
            if (headerDict != null) {
                for (NameValuePair entry : headerDict) {
                    getReq.setHeader(entry.getName(), entry.getValue());
                }
            }
            request = getReq;
        }
        try {
            HttpContext localContext = new BasicHttpContext();
            localContext.setAttribute(ClientContext.COOKIE_STORE, gCurCookieStore);
            response = httpClient.execute(request, localContext);
        } catch (ClientProtocolException cpe) {
            cpe.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return response;
    }

    /**
     * get方式或者post方式请求URL并解析
     *
     * @param url 请求的URL
     * @return 请求的返回的response
     */
    public HttpResponse getUrlResponse(String url) {
        return getUrlResponse(url, null, null, 0);
    }

    /**
     * get方式或者post方式请求URL并解析
     *
     * @param url         请求的URL
     * @param headerDict  请求求文件 可以为空，则用默认的头文件
     * @param postDict    post请求参数 如果为空，也自动调用get方式
     * @param timeout     请求超时时间 默认问5000毫秒
     * @param htmlCharset 请求页面的编码方式 可以为空  默认为utf-8
     * @return 请求的返回的html页面字符串
     */
    public String getUrlRespHtml(
            String url,
            List<NameValuePair> headerDict,
            List<NameValuePair> postDict,
            int timeout,
            String htmlCharset
    ) {
        String respHtml = "";
        String defaultCharset = "UTF-8";
        if ((null == htmlCharset) || htmlCharset.isEmpty()) {
            htmlCharset = defaultCharset;
        }
        try {
            HttpResponse response = getUrlResponse(url, headerDict, postDict, timeout);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                HttpEntity respEnt = response.getEntity();
                respHtml = EntityUtils.toString(respEnt, htmlCharset);
            }
        } catch (ClientProtocolException cpe) {
            cpe.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return respHtml;
    }

    /**
     * get方式或者post方式请求URL并解析
     *
     * @param url        请求的URL
     * @param headerDict 请求求文件 可以为空，则用默认的头文件
     * @param postDict   post请求参数 如果为空，也自动调用get方式
     * @return 请求的返回的html页面字符串
     */
    public String getUrlRespHtml(String url, List<NameValuePair> headerDict, List<NameValuePair> postDict) {
        return getUrlRespHtml(url, headerDict, postDict, 0, "");
    }

    /**
     * get方式或者post方式请求URL并解析
     *
     * @param url         请求的URL
     * @param htmlCharset 请求页面的编码方式 可以为空  默认为utf-8
     * @return 请求的返回的html页面字符串
     */
    public String getUrlRespHtml(String url, String htmlCharset) {
        return getUrlRespHtml(url, null, null, 0, htmlCharset);
    }

    /**
     * get方式或者post方式请求URL并解析
     *
     * @param url 请求的URL
     * @return 请求的返回的html页面字符串
     */
    public String getUrlRespHtml(String url) {
        return getUrlRespHtml(url, "UTF-8");
    }

    public interface UpdateProgressCallback {
        public void updateProgress(long currentSize, long totalSize);
    }


    /**
     * 下载文件
     *
     * @param url                   下载的url
     * @param fullFilename          保存本地文件路径和名字
     * @param headerDict            请求头设置
     * @param updateProgressCallbak 回调函数
     * @return 下载是否成功
     */
    public Boolean downlodFile(String url, File fullFilename, List<NameValuePair> headerDict, UpdateProgressCallback updateProgressCallbak) {
        Boolean downloadOk = Boolean.FALSE;
        HttpResponse response = getUrlResponse(url, headerDict, null, 0);
        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            HttpEntity respEnt = response.getEntity();
            System.out.println("isChunked" + respEnt.isChunked());
            System.out.println("Streaming" + respEnt.isStreaming());
            Boolean isStream = respEnt.isStreaming();
            if (isStream) {
                try {
                    InputStream fileInStream = respEnt.getContent();
                    FileOutputStream fileOutStream = new FileOutputStream(fullFilename);
                    long totalSize = respEnt.getContentLength();
                    byte[] tmpBuf = new byte[8192];
                    int bufLen = 0;
                    long downloadedSize = 0;
                    while ((bufLen = fileInStream.read(tmpBuf)) > 0) {
                        fileOutStream.write(tmpBuf, 0, bufLen);
                        downloadedSize += bufLen;
                        updateProgressCallbak.updateProgress(downloadedSize, totalSize);
                    }
                    fileOutStream.close();
                    downloadOk = Boolean.TRUE;
                } catch (IllegalStateException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return downloadOk;
    }




    /**
     * 得到一个文件的编码方式
     *
     * @param path 文件路径
     * @return 编码方式
     * @throws IllegalArgumentException
     * @throws IOException

    public String getFileEncode(String path) throws IllegalArgumentException, IOException {
    CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
    detector.add(new ParsingDetector(false));
    detector.add(JChardetFacade.getInstance());
    detector.add(ASCIIDetector.getInstance());
    detector.add(UnicodeDetector.getInstance());
    java.nio.charset.Charset charset = null;
    File f = new File(path);
    charset = detector.detectCodepage(f.toURI().toURL());
    if (charset != null)
    return charset.name();
    else
    return null;
    }

     */


}
